home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Chip 2000 October
/
CHIP Turkiye Ekim 2000.iso
/
prog
/
naps
/
04
/
setup.exe
/
Gnucleus
/
ViewTransfer.cpp
< prev
next >
Wrap
C/C++ Source or Header
|
2000-07-15
|
32KB
|
1,080 lines
/********************************************************************************
Gnucleus - A node application for the Gnutella network
Copyright (C) 2000 John Marshall
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
For support, questions, comments, etc...
E-Mail:
swabby@c0re.net
Address:
21 Cadogan Way
Nashua, NH, USA 03062
********************************************************************************/
// ViewTransfer.cpp : implementation file
//
#include "stdafx.h"
#include "Gnucleus.h"
#include "MainFrm.h"
#include "GnucleusDoc.h"
#include "ViewSearch.h"
#include "GnuTransfer.h"
#include "GnuHash.h"
#include "GnuSock.h"
#include "GnuControl.h"
#include "ViewTransfer.h"
#include "Base64.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CViewTransfer
IMPLEMENT_DYNCREATE(CViewTransfer, CFormView)
CViewTransfer::CViewTransfer()
: CFormView(CViewTransfer::IDD)
{
//{{AFX_DATA_INIT(CViewTransfer)
// NOTE: the ClassWizard will add member initialization here
//}}AFX_DATA_INIT
UpdateRate = 0;
FiveSecs = 0;
m_bItemsChanged = false;
}
CViewTransfer::~CViewTransfer()
{
}
void CViewTransfer::DoDataExchange(CDataExchange* pDX)
{
CFormView::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CViewTransfer)
DDX_Control(pDX, IDC_BUTTON_CANCEL_DOWN, m_CancelDown);
DDX_Control(pDX, IDC_BUTTON_CANCEL_UP, m_CancelUp);
DDX_Control(pDX, IDC_BUTTON_PAUSE, m_btnPause);
DDX_Control(pDX, IDC_STATIC_UPLOADS, m_stcUploads);
DDX_Control(pDX, IDC_STATIC_DOWNLOADS, m_stcDownloads);
DDX_Control(pDX, IDC_LIST_UPLOADS, m_lstUploads);
DDX_Control(pDX, IDC_LIST_DOWNLOADS, m_lstDownloads);
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CViewTransfer, CFormView)
//{{AFX_MSG_MAP(CViewTransfer)
ON_WM_SIZE()
ON_WM_TIMER()
ON_BN_CLICKED(IDC_BUTTON_CANCEL_DOWN, OnButtonCancelDown)
ON_BN_CLICKED(IDC_BUTTON_CANCEL_UP, OnButtonCancelUp)
ON_BN_CLICKED(IDC_BUTTON_PAUSE, OnButtonPause)
ON_NOTIFY(LVN_ITEMCHANGED, IDC_LIST_DOWNLOADS, OnItemchangedListDownloads)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CViewTransfer diagnostics
#ifdef _DEBUG
void CViewTransfer::AssertValid() const
{
CFormView::AssertValid();
}
void CViewTransfer::Dump(CDumpContext& dc) const
{
CFormView::Dump(dc);
}
#endif //_DEBUG
/////////////////////////////////////////////////////////////////////////////
// CViewTransfer message handlers
void CViewTransfer::OnInitialUpdate()
{
CFormView::OnInitialUpdate();
Doc = (CGnucleusDoc *) GetDocument();
// Initialize the list control
int offSet;
if(m_lstDownloads.GetScrollLimit(SB_VERT))
offSet = ::GetSystemMetrics(SM_CXVSCROLL) + 3;
else
offSet = 4;
CRect rect;
m_lstDownloads.GetWindowRect(&rect);
m_lstDownloads.InsertColumn(0, "File", LVCFMT_LEFT,
(rect.Width() - offSet) * 2/6, 0);
m_lstDownloads.InsertColumn(1, "Bytes", LVCFMT_RIGHT,
(rect.Width() - offSet) * 1/6, 1);
m_lstDownloads.InsertColumn( 2, "Status", LVCFMT_LEFT,
(rect.Width() - offSet) * 1/6, 2);
m_lstDownloads.InsertColumn( 3, "Completed", LVCFMT_LEFT,
(rect.Width() - offSet) * 1/6, 3);
m_lstDownloads.InsertColumn( 4, "Rate", LVCFMT_RIGHT,
(rect.Width() - offSet) * 1/6, 4);
m_lstDownloads.SetExtendedStyle(LVS_EX_FULLROWSELECT);
if(m_lstUploads.GetScrollLimit(SB_VERT))
offSet = ::GetSystemMetrics(SM_CXVSCROLL) + 3;
else
offSet = 4;
m_lstUploads.GetWindowRect(&rect);
m_lstUploads.InsertColumn(0, "File", LVCFMT_LEFT,
(rect.Width() - offSet) * 2/6, 0);
m_lstUploads.InsertColumn(1, "Bytes", LVCFMT_RIGHT,
(rect.Width() - offSet) * 1/6, 1);
m_lstUploads.InsertColumn( 2, "Status", LVCFMT_LEFT,
(rect.Width() - offSet) * 1/6, 2);
m_lstUploads.InsertColumn( 3, "Completed", LVCFMT_LEFT,
(rect.Width() - offSet) * 1/6, 3);
m_lstUploads.InsertColumn( 4, "Rate", LVCFMT_RIGHT,
(rect.Width() - offSet) * 1/6, 4);
m_lstUploads.SetExtendedStyle(LVS_EX_FULLROWSELECT);
// Set image lists
m_lstDownloads.SetImageList(GetSharedImageList(), LVSIL_SMALL);
m_lstUploads.SetImageList(GetSharedImageList(), LVSIL_SMALL);
// Disable buttons
m_btnPause.EnableWindow(FALSE);
m_CancelDown.EnableWindow(FALSE);
// Set the timer
DownloadTimer = SetTimer(1, 1000, 0);
UploadTimer = SetTimer(1, 1000, 0);
// Resize the window so all the controls adjust properly
GetParentFrame()->GetClientRect(&rect);
OnSize(SIZE_RESTORED, rect.right - 4, rect.bottom - 4);
// restore file list
m_ReadSavedTransfers();
}
void CViewTransfer::OnSize(UINT nType, int cx, int cy)
{
if(m_lstDownloads.m_hWnd != NULL)
{
RECT rectWnd,
rectDownloads,
rectUploads,
rectStcDown,
rectStcUp,
rectBtnPause,
rectBtnCancelUp,
rectBtnCancelDown;
GetWindowRect(&rectWnd);
m_lstDownloads.GetWindowRect(&rectDownloads);
m_lstUploads.GetWindowRect(&rectUploads);
m_stcDownloads.GetWindowRect(&rectStcDown);
m_stcUploads.GetWindowRect(&rectStcUp);
m_btnPause.GetWindowRect(&rectBtnPause);
m_CancelUp.GetWindowRect(&rectBtnCancelUp);
m_CancelDown.GetWindowRect(&rectBtnCancelDown);
int top_lstDownloads = rectDownloads.top - rectWnd.top - 2;
int left_lstDownloads = rectDownloads.left - rectWnd.left - 2;
// int right_lstDownloads = rectDownloads.right - rectDownloads.left;
// int bottom_lstDownloads = rectDownloads.bottom - rectDownloads.top;
// int top_lstUploads = rectUploads.top - rectWnd.top - 2;
int left_lstUploads = rectUploads.left - rectWnd.left - 2;
// int right_lstUploads = rectUploads.right - rectUploads.left;
// int bottom_lstUploads = rectUploads.bottom - rectUploads.top;
// int top_stcDown = rectStcDown.top - rectWnd.top - 2;
// int left_stcDown = rectStcDown.left - rectWnd.left - 2;
// int right_stcDown = rectStcDown.right - rectStcDown.left;
int bottom_stcDown = rectStcDown.bottom - rectStcDown.top;
// int top_stcUp = rectStcUp.top - rectWnd.top - 2;
int left_stcUp = rectStcUp.left - rectWnd.left - 2;
int right_stcUp = rectStcUp.right - rectStcUp.left;
int bottom_stcUp = rectStcUp.bottom - rectStcUp.top;
// int top_btnPause = rectBtnPause.top - rectWnd.top - 2;
int left_btnPause = rectBtnPause.left - rectWnd.left - 2;
int right_btnPause = rectBtnPause.right - rectBtnPause.left;
int bottom_btnPause = rectBtnPause.bottom - rectBtnPause.top;
// int top_btnCancelUp = rectBtnCancelUp.top - rectWnd.top - 2;
int left_btnCancelUp = rectBtnCancelUp.left - rectWnd.left - 2;
int right_btnCancelUp = rectBtnCancelUp.right - rectBtnCancelUp.left;
int bottom_btnCancelUp = rectBtnCancelUp.bottom - rectBtnCancelUp.top;
// int top_btnCancelDown = rectBtnCancelDown.top - rectWnd.top - 2;
int left_btnCancelDown = rectBtnCancelDown.left - rectWnd.left - 2;
int right_btnCancelDown = rectBtnCancelDown.right - rectBtnCancelDown.left;
int bottom_btnCancelDown = rectBtnCancelDown.bottom - rectBtnCancelDown.top;
m_lstDownloads.MoveWindow(left_lstDownloads, top_lstDownloads, cx - 17, cy / 2 - bottom_stcDown - bottom_btnCancelDown - 25);
m_CancelDown.MoveWindow (left_btnCancelDown, cy / 2 - 7 - bottom_btnCancelDown, right_btnCancelDown, bottom_btnCancelDown);
m_btnPause.MoveWindow (left_btnPause, cy / 2 - 7 - bottom_btnPause, right_btnPause, bottom_btnPause);
m_stcUploads.MoveWindow(left_stcUp, cy / 2 + 10, right_stcUp, bottom_stcUp);
m_lstUploads.MoveWindow(left_lstUploads, cy / 2 + bottom_stcUp + 10, cx - 17, cy / 2 - bottom_stcUp - bottom_btnCancelUp - 25);
m_CancelUp.MoveWindow (left_btnCancelUp, cy - bottom_btnCancelUp - 8, right_btnCancelUp, bottom_btnCancelUp);
// Resize columns
int offSet;
if(m_lstDownloads.GetScrollLimit(SB_VERT))
offSet = ::GetSystemMetrics(SM_CXVSCROLL) + 3;
else
offSet = 4;
CRect rect;
m_lstDownloads.GetWindowRect(&rect);
m_lstDownloads.SetColumnWidth(0, (rect.Width() - offSet) * 2/6);
m_lstDownloads.SetColumnWidth(1, (rect.Width() - offSet) * 1/6);
m_lstDownloads.SetColumnWidth(2, (rect.Width() - offSet) * 1/6);
m_lstDownloads.SetColumnWidth(3, (rect.Width() - offSet) * 1/6);
m_lstDownloads.SetColumnWidth(4, (rect.Width() - offSet) * 1/6);
if(m_lstUploads.GetScrollLimit(SB_VERT))
offSet = ::GetSystemMetrics(SM_CXVSCROLL) + 3;
else
offSet = 4;
m_lstUploads.GetWindowRect(&rect);
m_lstUploads.SetColumnWidth(0, (rect.Width() - offSet) * 2/6);
m_lstUploads.SetColumnWidth(1, (rect.Width() - offSet) * 1/6);
m_lstUploads.SetColumnWidth(2, (rect.Width() - offSet) * 1/6);
m_lstUploads.SetColumnWidth(3, (rect.Width() - offSet) * 1/6);
m_lstUploads.SetColumnWidth(4, (rect.Width() - offSet) * 1/6);
}
CFormView::OnSize(nType, cx, cy);
}
void CViewTransfer::OnTimer(UINT nIDEvent)
{
int decimal, sign;
if(nIDEvent == DownloadTimer)
{
QueryItem lstItem;
// Turn queued downloads into active downloads, if there's room available
int ActiveDownloads = 0;
for(int i = 0; i < m_lstDownloads.GetItemCount(); i++)
if("Downloading" == m_lstDownloads.GetItemText(i, m_lstDownloads.GetColumnNumber("Status")) ||
"Remotely queued" == m_lstDownloads.GetItemText(i, m_lstDownloads.GetColumnNumber("Status")) ||
-1 != m_lstDownloads.GetItemText(i, m_lstDownloads.GetColumnNumber("Status")).Find("Connecting"))
ActiveDownloads++;
i = 0;
while(i < m_lstDownloads.GetItemCount() && (ActiveDownloads < Doc->m_MaxDownloads || Doc->m_MaxDownloads == 0))
{
if(m_lstDownloads.GetItemText(i, m_lstDownloads.GetColumnNumber("Status") ) == "Queued")
{
m_lstDownloads.SetItemText(i, m_lstDownloads.GetColumnNumber("Status"), "Connecting");
GetQueryItem(i, 'D')->Connect( IPtoStr( GetQueryItem(i, 'D')->FileInfo.Host), GetQueryItem(i, 'D')->FileInfo.Port);
GetQueryItem(i, 'D')->Status = "Connecting";
m_bItemsChanged = true;
ActiveDownloads++;
}
i++;
}
// Update completed statuses
for(int row = 0; row < m_lstDownloads.GetItemCount(); row++)
{
CGnuTransfer *Item = GetQueryItem(row, 'D');
if(!Item)
{
RemoveRow(row, 'D');
return;
}
// Update Status
m_lstDownloads.SetItemText(row, m_lstDownloads.GetColumnNumber("Status"), Item->Status);
if("Downloading" == Item->Status )
{
float NewRate = ( (float)Item->BytesCompleted - (float)Item->OldBytesCompleted ) / (float)1024;
CString Rate = _fcvt( (NewRate + Item->OldRate) / (float) 2 , 2, &decimal, &sign );
Rate.Insert(decimal, ".");
m_lstDownloads.SetItemText(row, m_lstDownloads.GetColumnNumber("Rate"), Rate + " KB/s");
Item->OldBytesCompleted = Item->BytesCompleted;
Item->OldRate = NewRate;
UpdateRate = 0;
// Update the percentage
CString Percentage;
Percentage = _fcvt((float)Item->BytesCompleted / (float)Item->FileSize * (float)100, 0, &decimal, &sign );
if(Percentage == "")
Percentage = "0";
Percentage += "% )";
m_lstDownloads.SetItemText(row, m_lstDownloads.GetColumnNumber("Completed"), CommaIze( DWrdtoStr(Item->BytesCompleted)) + " ( " + Percentage);
}
else if("Completed" == m_lstDownloads.GetItemText(row, m_lstDownloads.GetColumnNumber("Status")) )
{
m_lstDownloads.SetItemText(row, m_lstDownloads.GetColumnNumber("Completed"), "");
m_lstDownloads.SetItemText(row, m_lstDownloads.GetColumnNumber("Rate"), "");
if(Doc->m_AutoClearDL)
RemoveRow(row, 'D');
m_bItemsChanged = true;
}
// Time out timed out items.
/*
*** THIS ERRORS OUT ON COMPLETION OF A PUSHED DOWNLOAD, NO IDEA WHY
if( Item->GetSecondsSinceLastContact() > Doc->m_TimeoutDownload )
{
GetQueryItem(row, 'D')->Status = "No response (paused)";
m_bItemsChanged = true;
GetQueryItem(row, 'D')->Pause();
}
*/
else if(Item->Status.Find("Connecting") != -1)
{
CString MaxDots;
for(int i = 0; i < Doc->m_TimeoutDownload / 5; i++)
MaxDots += ".";
if(Item->Status.Find(MaxDots) != -1)
{
Doc->GnuComm->NewPushRequest( Item->FileInfo );
// RemoveRow(row, 'D');
GetQueryItem(row, 'D')->Status = "Trying push";
}
if(FiveSecs >= 5)
{
Item->Status += '.';
FiveSecs = 0;
}
else
FiveSecs++;
m_lstDownloads.SetItemText(row, m_lstDownloads.GetColumnNumber("Rate"), "");
}
else
{
if(Item->FileSize == Item->BytesCompleted)
Item->Status = "Completed";
m_lstDownloads.SetItemText(row, m_lstDownloads.GetColumnNumber("Rate"), "");
}
}
if(m_bItemsChanged)
{
// update saved file of statuses
m_SaveAllTransfers();
m_bItemsChanged = false;
}
// update the button status for when text changes.
m_UpdateDownloadButtons();
}
if(nIDEvent == UploadTimer)
{
Doc->ActiveUploads = 0;
for(int i = 0; i < m_lstUploads.GetItemCount(); i++)
if("Uploading" == m_lstUploads.GetItemText(i, m_lstUploads.GetColumnNumber("Status")))
Doc->ActiveUploads++;
for(int row = 0; row < m_lstUploads.GetItemCount(); row++)
{
CGnuTransfer *Item = GetQueryItem(row, 'U');
if(!Item)
{
RemoveRow(row, 'U');
return;
}
if("Uploading" == m_lstUploads.GetItemText(row, m_lstUploads.GetColumnNumber("Status")) )
{
// If there's a bandwidth limitation set, allocate some
if(Doc->m_LimitUp)
Item->AllocBw = Doc->m_LimitUp * 1024 / Doc->ActiveUploads;
else
Item->AllocBw = -1;
// Update rate
float NewRate = ( (float)Item->BytesCompleted - (float)Item->OldBytesCompleted ) / (float)1024;
CString Rate = _fcvt( (NewRate + Item->OldRate) / (float) 2 , 2, &decimal, &sign );
Rate.Insert(decimal, ".");
m_lstUploads.SetItemText(row, m_lstUploads.GetColumnNumber("Rate"), Rate + " KB/s");
Item->OldBytesCompleted = Item->BytesCompleted;
Item->OldRate = NewRate;
// Update percentage
CString Percentage;
Percentage = _fcvt((float)Item->BytesCompleted / (float)Item->FileSize * (float)100, 0, &decimal, &sign );
if(Percentage == "")
Percentage = "0";
Percentage += "% )";
m_lstUploads.SetItemText(row, m_lstUploads.GetColumnNumber("Completed"), CommaIze( DWrdtoStr(Item->BytesCompleted)) + " ( " + Percentage);
}
else if("Completed" == m_lstUploads.GetItemText(row, m_lstUploads.GetColumnNumber("Status")) )
{
m_lstUploads.SetItemText(row, m_lstUploads.GetColumnNumber("Completed"), "");
m_lstUploads.SetItemText(row, m_lstUploads.GetColumnNumber("Rate"), "");
if(Doc->m_AutoClearUL)
RemoveRow(row, 'U');
}
else
m_lstUploads.SetItemText(row, m_lstUploads.GetColumnNumber("Rate"), "");
// Update Status
m_lstUploads.SetItemText(row, m_lstUploads.GetColumnNumber("Status"), Item->Status);
}
}
CFormView::OnTimer(nIDEvent);
}
void CViewTransfer::NewDownload(QueryItem Item, SOCKET sock)
{
m_bItemsChanged = true;
Item.Handle = m_lstDownloads.GetItemCount();
Item.TransferType = 'D';
if(!Item.Status.GetLength()) // check to see if they may be passed status
Item.Status = "Queued";
// Setup new download with unique file name
if(Item.LocalFileName.IsEmpty())
{
CFileFind finder;
CString increment_insert;
int increment = 1;
int period_index = Item.FileName.ReverseFind(_T('.'));
Item.LocalFileName = Item.FileName;
// check to see if it exists already.
while(finder.FindFile(((CGnucleusDoc *)GetDocument())->m_DownloadDir + "\\" + Item.LocalFileName))
{
increment_insert.Format("[%u]", increment++);
// rename
Item.LocalFileName = Item.FileName;
if(period_index == -1) // add to end if there is no period, thus no extension.
Item.LocalFileName += increment_insert;
else
Item.LocalFileName.Insert( period_index, increment_insert );
}
}
Doc->GnuComm->AddTransfer(Item, sock);
m_lstDownloads.InsertItem(Item.Handle, "");
m_lstDownloads.SetItemText(Item.Handle, m_lstDownloads.GetColumnNumber( "File"), Item.FileName);
m_lstDownloads.SetItemText(Item.Handle, m_lstDownloads.GetColumnNumber( "Bytes"), CommaIze(DWrdtoStr(Item.Size)));
m_lstDownloads.SetItemText(Item.Handle, m_lstDownloads.GetColumnNumber( "Status"), Item.Status);
int index = GetIconIndexFromName(Item.FileName);
if(index != -1)
{
m_lstDownloads.SetItem(Item.Handle, 0, LVIF_IMAGE, NULL, index, m_lstDownloads.GetColumnNumber("File" ) , 0, NULL);
}
}
extern std::map <GUID, QueryItem, CompareGuids> g_pushList;
void CViewTransfer::NewPushDownload(std::string& pushString, SOCKET sock)
{
if (pushString.size() > MAX_PATH)
{
// Hostile or buggy client, disconnect
CAsyncSocket tempSock;
tempSock.Attach (sock);
tempSock.Close ();
return;
}
DWORD ref = 0;
TCHAR guid[40];
TCHAR fileName[MAX_PATH];
guid[0] = fileName[0] = 0;
::sscanf (pushString.c_str (), "GIV %d: %32s/%*s", &ref, guid);
GUID tempGuid;
// shield your eyes from this next code
unsigned char* tempGuidPtr = (unsigned char*) &tempGuid;
::sscanf (guid, "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
&tempGuidPtr[0],
&tempGuidPtr[1],
&tempGuidPtr[2],
&tempGuidPtr[3],
&tempGuidPtr[4],
&tempGuidPtr[5],
&tempGuidPtr[6],
&tempGuidPtr[7],
&tempGuidPtr[8],
&tempGuidPtr[9],
&tempGuidPtr[10],
&tempGuidPtr[11],
&tempGuidPtr[12],
&tempGuidPtr[13],
&tempGuidPtr[14],
&tempGuidPtr[15]);
tempGuid.Data1 ^= ref; // We can't use the straight guid
tempGuid.Data2 ^= (ref << 1); // just xor some of the values in the guid
std::map <GUID, QueryItem, CompareGuids>::iterator tempIt = g_pushList.find (tempGuid);
if (tempIt == g_pushList.end ())
{
// It appears that there are malicious hosts that send out pushes.
// ASSERT (FALSE);
CAsyncSocket tempSock;
tempSock.Attach (sock);
tempSock.Close ();
return;
}
std::string::iterator it;
for (it = pushString.begin (); it != pushString.end (); it++)
{
if (*it == '/')
{
it++;
break;
}
}
std::string temp;
temp.assign (it, pushString.end ());
QueryItem item = (*tempIt).second;
item.FileName = temp.c_str ();
item.Index = ref;
item.Status = "Remotely queued";
NewDownload (item, sock);
g_pushList.erase (tempIt); // Remove the file from the PUSH list once the transfer begins
/*
((CGnucleusApp *) AfxGetApp())->TransferFrame->ShowWindow(SW_SHOW);
((CGnucleusApp *) AfxGetApp())->TransferFrame->BringWindowToTop();
*/
}
CGnuTransfer* CViewTransfer::GetQueryItem(int row, char type)
{
CGnuTransfer *Item = Doc->GnuComm->GetTransfer(row, type);
if(Item)
return Item;
else
return NULL;
return NULL;
}
void CViewTransfer::RemoveRow(int deadRow, char type)
{
Doc->GnuComm->RemoveTransfer(deadRow, type);
if(type == 'D')
{ for(int i = deadRow + 1; i < m_lstDownloads.GetItemCount(); i++)
{
if(GetQueryItem(i, 'D'))
GetQueryItem(i, 'D')->Handle--;
}
m_lstDownloads.DeleteItem(deadRow);
}
else
{
for(int i = deadRow + 1; i < m_lstUploads.GetItemCount(); i++)
{
if(GetQueryItem(i, 'U'))
GetQueryItem(i, 'U')->Handle--;
}
m_lstUploads.DeleteItem(deadRow);
}
m_bItemsChanged = true;
}
void CViewTransfer::OnButtonCancelDown()
// To have fun with multiple cancles and pauses go to the dialog view, get the properties
// of the listbox and turn off the check on single item selection
// but dont keep it like that until it works =)
{
int nItem;
POSITION pos = m_lstDownloads.GetFirstSelectedItemPosition();
while(pos != NULL)
{
pos = m_lstDownloads.GetFirstSelectedItemPosition(); // *** Other wise it skips selections because of deleation from front ***
nItem = m_lstDownloads.GetNextSelectedItem(pos);
RemoveRow(nItem, 'D');
m_bItemsChanged = true;
}
}
////////////////////////////////////////////////////////////
//! author="Nathan Brown"
//
//: Pauses and resumes files, depending on caption status.
void CViewTransfer::OnButtonPause()
{
int nItem = -1;
POSITION pos = m_lstDownloads.GetFirstSelectedItemPosition();
CString str_item_text;
// Same thing as above
while(pos != NULL)
{
nItem = m_lstDownloads.GetNextSelectedItem(pos);
str_item_text = m_lstDownloads.GetItemText(nItem, m_lstDownloads.GetColumnNumber( "Status") );
if(str_item_text.Find("Connecting") != -1 ||
str_item_text == "Remotely queued" ||
str_item_text == "Downloading" )
{
GetQueryItem(nItem, 'D')->Pause();
}
else
{
// this resumes the file, resetting the sock and re-useing the CGnuTransfer object,
GetQueryItem(nItem, 'D')->m_hSocket = INVALID_SOCKET;
GetQueryItem(nItem, 'D')->Create(0, SOCK_STREAM, FD_READ | FD_CONNECT | FD_CLOSE, NULL);
GetQueryItem(nItem, 'D')->Connect( IPtoStr( GetQueryItem(nItem, 'D')->FileInfo.Host), GetQueryItem(nItem, 'D')->FileInfo.Port);
GetQueryItem(nItem, 'D')->Status = "Connecting";
}
}
}
struct SaveItem
{
char FileName[256]; // path to remote file
char LocalFileName[256]; // file name in local save path.
IP Host;
WORD Port;
DWORD Size;
DWORD Speed;
DWORD Index;
int Handle;
GUID Guid;
};
////////////////////////////////////////////////////////////
//! author="Nathan Brown"
//
//: Reads saved transfers from ini incase of crash, etc.
void CViewTransfer::m_ReadSavedTransfers(void)
{
if(!this)
return;
// Filter Settings
int loop;
CString str_file_name,
str_server_name_port;
DWORD dw_file_size = 0;
LVFINDINFO FindInfo;
SaveItem transfer_item;
CFileFind finder;
for (loop = 0; ; ++loop)
{
// gather items for connections
QueryItem qi_transfer_item;
CString temp;
temp.Format ("File%2.2d", loop);
if (GetPrivateProfileStruct ("Transfers", temp, (void *) &transfer_item, sizeof(SaveItem), ".\\Gnucleus.ini") )
{
/* // think I got it fixed, can't use this when using different local file names
// Check to see if file is already in transfer list
FindInfo.flags = LVFI_PARTIAL|LVFI_STRING;
FindInfo.psz = &transfer_item.FileName[0];
// some kind of weird problem lurks here, crashes dead, no explenation.
if( m_lstDownloads.FindItem(&FindInfo) != -1 )
continue; // file already in, may be different server, but continue
// if not, add to list as queued.
*/
qi_transfer_item.FileName = transfer_item.FileName;
if(Doc->m_ResumeDL)
qi_transfer_item.Status = "Queued";
else
qi_transfer_item.Status = "Restored";
qi_transfer_item.Guid = transfer_item.Guid;
qi_transfer_item.Handle = transfer_item.Handle;
qi_transfer_item.Host = transfer_item.Host;
qi_transfer_item.Port = transfer_item.Port;
qi_transfer_item.Size = transfer_item.Size;
qi_transfer_item.Speed = transfer_item.Speed;
qi_transfer_item.IconIndex = 0;
qi_transfer_item.Index = transfer_item.Index;
qi_transfer_item.Reverse = 0;
qi_transfer_item.SortBy = 0;
// and last and most importantly:
qi_transfer_item.BytesCompleted = 0;
if(finder.FindFile(((CGnucleusDoc *)GetDocument())->m_DownloadDir + "\\" + transfer_item.LocalFileName)) // if it's there use the saved filesize
{
int length = 0;
finder.FindNextFile();
if( (length = finder.GetLength()) )
qi_transfer_item.BytesCompleted = length;
qi_transfer_item.LocalFileName = transfer_item.LocalFileName;
}
else
qi_transfer_item.LocalFileName.Empty();
NewDownload(qi_transfer_item);
}
else
{
break;
}
}
}
////////////////////////////////////////////////////////////
//! author="Nathan Brown"
//
//: Saves all transfers in ini file useing base64 encoding
void CViewTransfer::m_SaveAllTransfers(void)
{
// Filter Settings
int loop;
CString str_file_name,
str_server_name_port;
CString temp_key;
SaveItem transfer_item;
QueryItem qi_transfer_item;
// Clear out items
for (loop = 0; true; ++loop)
{
temp_key.Format ("File%2.2d", loop);
if (GetPrivateProfileStruct("Transfers", temp_key, (void *) &transfer_item, sizeof(SaveItem), ".\\Gnucleus.ini") > 0)
WritePrivateProfileStruct ("Transfers", temp_key, NULL, sizeof(SaveItem), ".\\Gnucleus.ini"); // remove
else
break;
}
// write out current transfers
for (loop = 0; loop < m_lstDownloads.GetItemCount(); ++loop)
{
temp_key.Format ("File%2.2d", loop);
qi_transfer_item = GetQueryItem(loop, 'D')->FileInfo;
strcpy(transfer_item.FileName, qi_transfer_item.FileName);
strcpy(transfer_item.LocalFileName, qi_transfer_item.LocalFileName);
transfer_item.Guid = qi_transfer_item.Guid;
transfer_item.Handle = qi_transfer_item.Handle;
transfer_item.Host = qi_transfer_item.Host;
transfer_item.Port = qi_transfer_item.Port;
transfer_item.Size = qi_transfer_item.Size;
transfer_item.Speed = qi_transfer_item.Speed;
transfer_item.Index = qi_transfer_item.Index;
WritePrivateProfileStruct ("Transfers", temp_key, (void *)&transfer_item, sizeof(SaveItem), ".\\Gnucleus.ini");
}
}
////////////////////////////////////////////////////////////
//! author="Nathan Brown"
//
//: Maintains correct cancel and resume/pause button status
void CViewTransfer::m_UpdateDownloadButtons(void)
{
if(m_lstDownloads.GetSelectedCount())
{
int n_item;
bool b_pause = false,
b_activate = false;
POSITION pos = m_lstDownloads.GetFirstSelectedItemPosition();
while(pos)
{
n_item = m_lstDownloads.GetNextSelectedItem(pos);
CString str_item_text = m_lstDownloads.GetItemText(n_item, m_lstDownloads.GetColumnNumber( "Status"));
if(str_item_text.Find("Connecting") != -1 ||
str_item_text == "Remotely queued" ||
str_item_text == "Downloading" )
{
b_pause = true;
}
// need to make sure all possible strings that can resume are listed here.
if(str_item_text == "Paused" ||
str_item_text == "Queued" ||
str_item_text == "Restored" ||
str_item_text == "Connection Refused" ||
str_item_text == "HTTP 404 Error" ||
str_item_text == "HTTP 200 Error" ||
str_item_text == "Remotely Canceled" ||
str_item_text == "Trying push" ||
str_item_text == "Bad Header")
{
b_activate = true;
}
// make sure we are only going one way. disable otherwise.
if(b_activate && b_pause)
{
m_CancelDown.EnableWindow(TRUE); // can cancel if any selected
m_btnPause.EnableWindow(FALSE);
return;
}
}
m_CancelDown.EnableWindow(TRUE);
// well it all went well, so enable the button one way or the other
if(b_activate || b_pause)
{
m_btnPause.SetWindowText(b_activate ? "Activate" : "Pause" );
m_btnPause.EnableWindow(TRUE);
}
else
{
m_btnPause.EnableWindow(FALSE);
}
}
else
{
m_CancelDown.EnableWindow(FALSE);
m_btnPause.EnableWindow(FALSE);
}
}
////////////////////////////////////////////////////////////
//! author="Nathan Brown"
//
//: Maintains correct cancel and resume/pause button status
void CViewTransfer::OnItemchangedListDownloads(NMHDR* pNMHDR, LRESULT* pResult)
{
NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
*pResult = 0;
if( (pNMListView->uChanged & LVIF_STATE) == LVIF_STATE )
{
// Doesn't work for when the text changes, need to fix that later.
if((pNMListView->uNewState & LVIS_SELECTED)
| (pNMListView->uOldState & LVIS_SELECTED))
m_UpdateDownloadButtons();
}
else // if what changed is not what we are interested in, don't worry about it.
return;
}
void CViewTransfer::NewUpload(CString Header, SOCKET sock)
{
// If its past the max uploads drop it
if(Doc->m_MaxUploads)
if(Doc->m_MaxUploads <= Doc->ActiveUploads)
return;
DWORD index;
TCHAR name[256];
DWORD bytes = 0;
::sscanf(Header, "GET /get/%ld/%s HTTP/1.0\r\n", &index, name);
CString FileName(Header.Mid( Header.Find(name), Header.Find(" HTTP/1.0") - Header.Find(name)));
bool found = 0;
if(Header.Find("bytes=") != -1)
{
int pos = Header.Find("bytes=") + 6;
bytes = atol( Header.Mid(pos, Header.Find("-\r\n") - pos));
found = 1;
}
QueryItem Item;
if(found)
Item.BytesCompleted = bytes;
else
Item.BytesCompleted = 0;
// Find file in the list
std::vector<SharedFile>::iterator itName;
std::vector<DWORD>::iterator itSize;
CString ShortName;
DWORD loop = 0;
for(loop = 0, itName = Doc->SharedFiles.begin(), itSize = Doc->SharedSizes.begin();
itName != Doc->SharedFiles.end(), itSize != Doc->SharedSizes.end();
loop++, itName++, itSize++)
{
if(loop == index)
if(FileName != (*itName).FileName)
return;
else
{
ShortName = (*itName).FileName;
Item.FileName = (*itName).FileDir;
Item.Size = *itSize;
Item.Index = loop;
}
}
if(index > loop)
return;
// Setup structure and list
Item.Handle = m_lstUploads.GetItemCount();
Item.TransferType = 'U';
Item.Status = "Connecting";
m_lstUploads.InsertItem(Item.Handle, "" );
m_lstUploads.SetItemText(Item.Handle, m_lstUploads.GetColumnNumber( "File"), ShortName);
m_lstUploads.SetItemText(Item.Handle, m_lstUploads.GetColumnNumber( "Bytes"), CommaIze(DWrdtoStr(Item.Size)));
m_lstUploads.SetItemText(Item.Handle, m_lstUploads.GetColumnNumber( "Status"), Item.Status);
int icon = GetIconIndexFromName(ShortName);
if(icon != -1)
m_lstUploads.SetItem(Item.Handle, 0, LVIF_IMAGE, NULL, icon, m_lstUploads.GetColumnNumber( "File"), 0, NULL);
// A normal upload
if(sock)
{
Doc->GnuComm->AddTransfer(Item, sock);
GetQueryItem(Item.Handle, 'U')->StartSending();
}
// A push upload
else
{
CGnuTransfer *Push = GetQueryItem(16000, 'U');
if(Push)
{
Push->FileInfo = Item;
Push->Handle = Item.Handle;
Push->FileSize = Item.Size;
GetQueryItem(Item.Handle, 'U')->StartSending();
}
}
}
void CViewTransfer::OnButtonCancelUp()
{
int nItem;
POSITION pos = m_lstUploads.GetFirstSelectedItemPosition();
while(pos != NULL)
{
pos = m_lstUploads.GetFirstSelectedItemPosition(); // *** Other wise it skips selections because of deleation from front ***
nItem = m_lstUploads.GetNextSelectedItem(pos);
RemoveRow(nItem, 'U');
}
}